/**
 * 
 */
package info.niwota.fwrite;

import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * @author qiangli
 *
 */
public class NoteListActivity extends Activity implements OnItemClickListener, OnClickListener {

	private static final String TAG = "NoteListActivity";
	

	private static final int DIALOG_FLAG = 10;

	private static final int DIALOG_SORT_BY = 12;
	
	private static final int DIALOG_REMOVE_NOTE = 13;
	
	private static final int DIALOG_BC = 14;
	
	protected NoteListAdapter adapter;
	
	protected ImageButton mActions;

	protected ListView mList;
	
	protected TextView mTitle;

	protected Document selectedDocument;

	protected ImageButton mActionSortBy;

	protected View mNavibar;

	protected ImageButton mNaviTop;

	protected ImageButton mNaviBack;

	protected ImageButton mNaviBC;

	protected Button mNaviAddNote;

	protected Document currentDocument;

	@Override
	public void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	
		if (Debug.DEBUG) {
			Log.d(TAG, "onCreate: "  + savedInstanceState);
		}
		
		setContentView(R.layout.list_note);
		
		initRes();
	}

	protected void initRes() {
		mTitle = (TextView) findViewById(R.id.title);
		mTitle.setText(R.string.title_notes);
		
		mNavibar = findViewById(R.id.navibar);
		mNaviTop = (ImageButton) findViewById(R.id.navi_top);
		mNaviBack = (ImageButton) findViewById(R.id.navi_back);
		mNaviBC = (ImageButton) findViewById(R.id.navi_bc);
		mNaviAddNote = (Button) findViewById(R.id.navi_addnote);
		
		mActions = (ImageButton) findViewById(R.id.menu_actions);
		
		mActionSortBy = (ImageButton) findViewById(R.id.actions_sort_by);
		
		mList = (ListView) findViewById(android.R.id.list);
		//
		mActions.setOnClickListener(this);
		mActionSortBy.setOnClickListener(this);
		
		mList.setOnItemClickListener(this);
		
		mNaviTop.setOnClickListener(this);
		mNaviBack.setOnClickListener(this);
		mNaviBC.setOnClickListener(this);
		mNaviAddNote.setOnClickListener(this);
	}

	@Override
	protected void onPause() {
		super.onPause();
		
		if (Debug.DEBUG) {
			Log.d(TAG, "onPause");
		}
		
		if (mList != null) {
			unregisterForContextMenu(mList);
		}
	}

	@Override
	protected void onResume() {
		super.onResume();
		
		if (Debug.DEBUG) {
			Log.d(TAG, "onResume");
		}
		
		if (mList != null) {
			registerForContextMenu(mList);
		}
	}

	@Override
	protected void onStart() {
		super.onStart();
		if (Debug.DEBUG) {
			Log.d(TAG, "onStart");
		}
	}

	@Override
	public void onStop() {
		super.onStop();
		if (Debug.DEBUG) {
			Log.d(TAG, "onStop");
		}
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		//
		if (Debug.DEBUG) {
			Log.d(TAG, "onDestroy");
		}
	}
	
	private void initList(List<Document> notes, int order) {
		adapter = new NoteListAdapter(this, notes, order);
		
		ListView lv = mList;
		lv.setAdapter(adapter);
		lv.setItemsCanFocus(false);
		lv.setChoiceMode(ListView.CHOICE_MODE_NONE);
		lv.setEnabled(true);
	}
	
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		if (adapter == null) {
			return true;
		}
		AdapterView.AdapterContextMenuInfo mi = (AdapterView.AdapterContextMenuInfo) item
				.getMenuInfo();
		if (mi == null) {
			return true;
		}
		int pos = mi.position;
		Document doc = adapter.getItem(pos);
		//
		switch (item.getItemId()) {
		case R.id.notes_view_context_menu_id:
			doViewNote(doc);
			break;
		case R.id.notes_edit_context_menu_id:
			doEditNote(doc);
			break;
		case R.id.notes_delete_context_menu_id:
			doDeleteNote(doc);
			break;
		case R.id.notes_flag_context_menu_id:
			doShowFlags(doc);
			break;
		case R.id.notes_list_context_menu_id:
			doListSubnotes(doc);
			break;
		case R.id.notes_add_context_menu_id:
			doListSubnotes(doc);
			addNote(doc);
			break;
		default:
		}
		return true;
	}
	
	protected void doDeleteNote(Document doc) {
		if (doc.isEmpty()) {
			deleteNote(doc);
		} else {
			doShowDeleteConfirm(doc);
		}
	}

	protected void deleteNote(Document doc) {
		doc.delete();
		adapter.delete(doc);
	}
	
	protected void doShowDeleteConfirm(Document doc) {
		selectedDocument = doc;
		showDialog(DIALOG_REMOVE_NOTE);
	}
	
	private Dialog createBCDialog() {
		return MenuDialogs.createBreadCrumbDialog(this, new MenuCallback() {
			public void perform(MenuInfo mi) {
				Document doc = (Document) mi.data;
				doListSubnotes(doc);
			}
		});
	}

	private Dialog createRemoveNoteDialog() {
		Dialog.OnClickListener cl = new Dialog.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				switch (which) {
				case DialogInterface.BUTTON_POSITIVE:
					deleteNote(selectedDocument);
					break;
				default:
				}
			}
		};
        LayoutInflater factory = LayoutInflater.from(this);
        final View view = factory.inflate(R.layout.note_remove, null);
		AlertDialog.Builder b = new AlertDialog.Builder(this);
		b.setIcon(android.R.drawable.ic_dialog_alert);
		b.setTitle(R.string.action_delete_note);
		b.setView(view);
		b.setPositiveButton(android.R.string.ok, cl);
		b.setNegativeButton(android.R.string.cancel, cl);
		//
		return b.create();
	}

	private Dialog createSortMenuDialog() {
		return MenuDialogs.createSortMenuDialog(this, R.string.sort_by,
				new MenuCallback() {
					public void perform(MenuInfo mi) {
						switch(mi.id) {
						case R.string.sort_by_flag:
							doSort(Document.SORT_FLAG);
							break;
						case R.string.sort_by_date:
							doSort(Document.SORT_DATE);
							break;
						}
					}
				});
	}
	
	
	protected void doShowTop() {
		doListSubnotes(null);
	}
	
	protected void doListSubnotes(final Document doc) {
		if (Debug.DEBUG) {
			Log.d(TAG, "doShowSubnotes: " + doc);
		}
		
		currentDocument = doc;
		
		//
		mNavibar.setVisibility(View.VISIBLE);
		mNavibar.setEnabled(true);
		
		//
		int order = Document.SORT_FLAG;
		
		if (doc == null) {
			mTitle.setText(R.string.action_top);
			mTitle.setCompoundDrawablesWithIntrinsicBounds(R.drawable.top16, 0, 0, R.drawable.divider_horizontal_light);
			mTitle.setEnabled(false);
			
			mNaviTop.setVisibility(View.GONE);
			mNaviTop.setEnabled(false);
			mNaviBack.setVisibility(View.GONE);
			mNaviBack.setEnabled(false);
			mNaviBC.setVisibility(View.GONE);
			mNaviBC.setEnabled(false);
		} else {
			order = doc.getOrder();
			
			final String id = doc.getId();
			final int flag = doc.getFlagIcon();
		
			mTitle.setText(id);
			mTitle.setCompoundDrawablesWithIntrinsicBounds(flag, 0, 0, R.drawable.divider_horizontal_light);
			mTitle.setEnabled(false);
			
			mNaviTop.setVisibility(View.VISIBLE);
			mNaviTop.setEnabled(true);
			mNaviBack.setVisibility(View.VISIBLE);
			mNaviBack.setEnabled(true);
			mNaviBC.setVisibility(View.VISIBLE);
			mNaviBC.setEnabled(true);
		}
		
		mNaviAddNote.setVisibility(View.VISIBLE);
		mNaviAddNote.setEnabled(true);

		//
		List<Document> notes = DocumentHelper.list(doc);
		initList(notes, order);
	}
	
	protected void doNaviBack() {
		final Document c = currentDocument;
		if (Debug.DEBUG) {
			Log.d(TAG, "doNaviBack: " + c);
		}
		if (c == null) {
			doShowTop();
			return;
		}
		//
		Document pdoc = c.getParentDocument();
		doListSubnotes(pdoc);
	}
	

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.note_list_context, menu);
	}

	protected void doEditNote(Document doc) {
		currentDocument = doc;
	}

	protected void doViewNote(Document doc) {
		if (Debug.DEBUG) {
			Log.d(TAG, "doViewNote: " + doc);
		}
		currentDocument = doc;
	}
	
	protected void doNaviBC() {
		if (currentDocument == null) {
			return;
		}
		showDialog(DIALOG_BC);
	}

	public void onItemClick(AdapterView<?> av, View v, int pos, long id) {
		if (Debug.DEBUG) {
			Log.d(TAG, "onItemClick pos: " + pos + " id: " + id);
		}
		doNoteSelected(av, v, pos, id);
	}

	private void doNoteSelected(AdapterView<?> av, View v, int pos, long id) {
		try {
			Document doc = (Document) av.getAdapter().getItem(pos);
			
			//if doc has sub notes, show list
			int type = doc.getType();
			if (type == Document.TYPE_LIST) {
				doListSubnotes(doc);
				return;
			}

			//note
			//if empty, open in edit mode
			if (doc.isEmpty()) {
				doEditNote(doc);
				return;
			}
			
			//view note
			doViewNote(doc);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	protected void doSort(int by) {
		if (adapter != null) {
			adapter.order(by);
			
			updateSortIcon();
		}
	}

	private void updateSortIcon() {
		int ic = adapter.getSortIcon();
		mActionSortBy.setImageResource(ic);
	}
	
	protected void addNote(Document parent) {
		try {
			if (!mList.isShown()) {
				doListSubnotes(parent);
			}
			Document doc = DocumentHelper.add(parent);
			adapter.add(doc);
			//TODO get item pos for sorted by date
			mList.setSelection(adapter.getCount() - 1);
		} catch (Exception e) {
			showError(e);
			if (Debug.DEBUG) {
				e.printStackTrace();
			}
		}
	}
	
	protected void doShowFlags(Document doc) {
		selectedDocument = doc;
		showDialog(DIALOG_FLAG);
	}

	private Dialog createFlagDialog() {
		return MenuDialogs.createFlagDialog(this, R.string.action_flag,
				new MenuCallback() {
					public void perform(MenuInfo mi) {
						final double flag = MenuDialogs.getFlagValues(mi.id);	
						final Document doc = selectedDocument;
						if (doc != null) {
							double oflag = doc.getFlag();
							if (flag == oflag) {
								//ignore
								return;
							}
							try {
								if (mList.isShown()) {
									doc.setFlag(flag);
									doc.save();
						
									//
									if (adapter != null) {
										int sort = adapter.getSortBy();
										if (sort == Document.SORT_FLAG) {
											//reorder
											adapter.order();
										} else {
											adapter.notifyDataSetChanged();
										}
									}
								} else {
									//edit mode
									doc.setFlag(flag);
									doc.save();
									updateTitleIcon(doc.getFlagIcon());
								}
							} catch (Exception e) {
								showError(e);
							}
						}
					}
				});
	}
	
	public void onClick(View v) {
		int id = v.getId();
		if (Debug.DEBUG) {
			Log.d(TAG, "onClick id: " + id);
		}
		
		switch(id) {
		case R.id.menu_actions:
			doMenuAction();
			break;
		case R.id.title:
			doTitleAction();
			break;
		case R.id.navi_top:
			doShowTop();
			break;
		case R.id.navi_back:
			doNaviBack();
			break;
		case R.id.navi_addnote:
			addNote(currentDocument);
			break;
		case R.id.navi_bc:
			doNaviBC();
			break;
		case R.id.actions_sort_by:
			showDialog(DIALOG_SORT_BY);
			return;
		default:
			if (Debug.DEBUG) {
				Log.d(TAG, "onClick default: "+ id);
			}
		}
	}
	

	protected void doTitleAction() {
	}

	protected void doMenuAction() {
	}

	protected void fixIssue3674(final Window w) {
		w.setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
		// Issue 3674
		w.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
	}
	
	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		fixIssue3674(dialog.getWindow());
		
		switch (id) {
		case DIALOG_BC:
			final ListView nlv = ((AlertDialog) dialog).getListView();
			final NoteListAdapter nla = (NoteListAdapter) nlv.getAdapter();
			List<Document> docs = DocumentHelper.createBreadCrumb(currentDocument);
			nla.setAll(docs);
			break;
		case DIALOG_REMOVE_NOTE:
			if (selectedDocument != null) {
				FdocView fdv = (FdocView) dialog.findViewById(R.id.note_remove_fdoc);
				selectedDocument.show(fdv);
			}
			break;
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_FLAG:
			return createFlagDialog();
		case DIALOG_SORT_BY:
			return createSortMenuDialog();
		case DIALOG_REMOVE_NOTE:
			return createRemoveNoteDialog();
		case DIALOG_BC:
			return createBCDialog();
		default:
		}
		
		return super.onCreateDialog(id);
	}
	
	private void updateTitleIcon(int icon) {
		mTitle.setCompoundDrawablesWithIntrinsicBounds(
				icon, 0, 0,
				R.drawable.divider_horizontal_light);
	}
	
	protected void showError(Throwable e) {
		try {
			Toast.makeText(this, e.getMessage() + "", Toast.LENGTH_SHORT).show();
		} catch (Throwable t) {
			Log.d(TAG, "showError " + t);
		}
	}
}
